# 概要：
# 图文成片 剪辑音乐当背景乐 一张图片和文字一段 时长以文字多少为准

# 注意事项：
# 凡是和坐标有关的需要考虑 电脑分辨率 软件的布局 文件框位置
# 根据图片的大小和数量来决定文字的缩放，目前只有横板
# 一遍邮箱通信流程只出一张图片对应的文字视频，需是完整的
# 发过来的图片名字里面不能有"pic"
# 邮箱中图片的顺序就是实际文件中的顺序
# 剪映云pc不能删除，只能手机删除
# 以回复的时候的主题为一个流程

# 待完成：
# -修改打开软件的方式
# -修改邮箱通信方式，去掉返回图片链接这一步，和传入时间戳合并，即传入mp3的时候把时间戳也传了 然后是传图片和文字
# -图片及和合成的视频放到一个文件夹，命名为按顺序01234
# -邮箱返回文字格式 前面对应到指定图上01234 小段图片和成片视频放到子文件夹
# -以收到文字为信号开始剪辑，文字前需指定匹配到哪个图片，因为之前可以保存多个图片
# 使用剪映云空间进行视频的确认，不需要邮箱返回成片和等待确认了
# 新增在PC端定时发布，移动端只是查看确认
# 流程内部有一步是将所有视频合并，合并的时候音乐根据时间需要重新匹配
# 进行多小段音乐拼接

# 待优化：
# 目前播放速度（word_speed）是1s一个字，后续根据音乐的节拍来决定切图片的速度，即节拍和文字、图片切换要对应上
# 优化：素材过多一个框不下的时候 可以把素材框拉大全选，拖完再恢复

import smtplib
import eyed3
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from pydub import AudioSegment
import email
import imaplib
import os
import shutil
import time
import traceback
import zipfile
from email.header import decode_header, Header
from email.utils import parseaddr
from pathlib import Path
import datetime
import pyautogui
import pyperclip
from moviepy.editor import VideoFileClip

DEBUG = 0

remote_server_url = 'imap.qq.com'
email_url = "3324564761@qq.com"  # 当前使用邮箱
password = "ioaeproulegrchff"
email_msg_to = "1984832368@qq.com"  # 发送邮箱
check_time = 10 #n 秒检测一次是否更新

publish_platform = ["bz", "dy"] #发布平台

rewrite_print = print
def print(*arg):
   rewrite_print(*arg)
   output_dir = "log_file"
   if not os.path.exists(output_dir):
         os.makedirs(output_dir)
   log_name = 'log.txt' # 日志文件名称
   filename = os.path.join(output_dir, log_name)
   rewrite_print(*arg,file=open(filename,"a")) # 写入文件

def print_d(*arg): #仿真调试用
    if DEBUG == 1:
        print('------调试打印开始-----')
        print(*arg)
        print('------调试打印结束-----\r\n')


class email_data:
    def __init__(self):
        self.From = ""
        self.Subject = ""
        self.Date = ""
        self.filename = ""
        self.count = 0
        self.main_body = ""


    def printf(self, who):
        print(f'==========================================以上为调试，以下为{who}的真实有效数据========================================')
        print("From :% s ; Subject:% s ;  Date:% s ;  filename:% s ;  count:% s ;  main_body:% s ; " % (self.From, self.Subject, self.Date, self.filename, self.count, self.main_body))
        print(f'==========================================以上为{who}的真实有效数据==================================================')

    def reset(self):
        self.From = ""
        self.Subject = ""
        self.Date = ""
        self.filename = ""
        self.main_body = ""  #邮箱


class doc_function():  # 文件操作
    def save_data_txt(data):  # 添加数据到文件
        info_str = str(data)
        info_str += '\r\n'
        print(info_str)
        with open('flash_tool.log', 'a') as lead:
            lead.write(info_str)

    def set_data(data):  # 重写文件
        data_w = "data  " + data
        fi = open('data.txt', 'w', encoding='utf-8')
        fi.write(data_w)

    def mkdir(path):  # 新建文件夹
        folder = os.path.exists(path)

        if not folder:  # 判断是否存在文件夹如果不存在则创建为文件夹
            os.makedirs(path)  # makedirs 创建文件时如果路径不存在会创建这个路径
            print("---  new folder...  ---")
        else:
            print("folder is:", path)

    def copyfile(srcfile, dstpath):  # 复制文件
        if not os.path.isfile(srcfile):
            print("%s not exist!" % (srcfile))
        else:
            fpath, fname = os.path.split(srcfile)  # 分离文件名和路径
            if not os.path.exists(dstpath):
                os.makedirs(dstpath)  # 创建路径
            shutil.copy(srcfile, dstpath + fname)  # 复制文件

    def file_zip(start_file, zip_dir):  # 压缩文件
        # start_dir 要压缩的文件
        # zip_file 输出zip文件的路径
        fpath_start_dir, fname = os.path.split(start_file)  # 分离文件名和路径

        zip_file = zip_dir + '.zip'
        z = zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED)
        print(z)
        for path, dirname, file_name in os.walk(fpath_start_dir):
            # print("文件夹根路径：", path)
            fpath = path.replace(fpath_start_dir, '')  # 去除根路径名称
            # print("--去除根路径：", fpath)
            fpath = fpath and fpath + os.sep  # 在原fpath加上\
            # print("****去除根路径+\ ：", fpath)

            for filename in file_name:  # 逐个循环读取文档名称
                if filename.find(fname) >= 0:
                    # print(filename)
                    z.write(os.path.join(path, filename), fpath + filename)  # 实现在输出路径的Zip压缩操作
        z.close()


    # def get_web():
        # if os.path.isfile("cfg.txt"):
        #     f = open(r"cfg.txt", "r", encoding="utf-8")
        #     data = f.read()
        #     reg = 'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
        #     url = re.findall(reg, data)
        #     return url[-1]  # 假如地址在这一行的最后一个位置
        # else:
        #     print(" cfg.txt is not accessible, please creat!!!")
        #     sys.exit()

    def file_unzip_download(unzip_file):
        print(f"开始进行解压缩并下载···")

        zip_file = zipfile.ZipFile(unzip_file)
        fpath, fname = os.path.split(unzip_file)
        out_file = fpath + "\\unzip"
        if os.path.isdir(out_file):
            shutil.rmtree(out_file)
            os.mkdir(out_file)
        else:
            os.mkdir(out_file)
        for names in zip_file.namelist():
            zip_file.extract(names, out_file)
        zip_file.close()
        folder = Path(out_file.strip())
        result = list(folder.rglob(f'*{".hex"}*'))  # 只要hex文件
        print(result[0])  # 默认一个压缩包只有一个文件
        flash_file = str(result[0])
        # 进行文件的各种操作处理
        shutil.rmtree(out_file)

    def search_file(key_word, self_path=None):  # 查找的关键字 self_path是自定义路径
        folder_str = os.path.join(os.getcwd(), qq_email_rx.Subject)  # 刘森 新世界
        if self_path != None:
            folder_str = self_path

        folder = Path(folder_str.strip())
        print(folder)
        if folder.exists():
            print("开始根据关键字查找文件···")
        else:
            print("未找到存放关键字对应文件的文件夹")
            return None

        result = list(folder.rglob(f'*{key_word}*'))
        if not result:
            print(f'在{folder} 下未找到关键字名称 {key_word} 的文件夹或文件')
            return None
        else:
            print(f'在{folder} 下找到关键字名称 {key_word} 的文件夹或文件{result}')
            return result

    def get_str_row_column(words): #获取字符串中行数和列的最大字符数，返回两者的最大值
        row = words.count("\n") + 1

        # 存储所有的相同字符之间的距离
        length = []
        loc = 0
        last_loc = 0

        while words.find("\n", loc+1) != -1:
            loc = words.find("\n", loc+1)

            length.append(loc - last_loc)
            last_loc = loc

        length.append(len(words) - last_loc) # 获取最后一行长度
        # print(length)
        # print(f'最大长度：{max(length)}')
        column = max(length)
        # print(max(row, column))
        return max(row, column)

    def delete_files(file_path):
        if os.path.exists(file_path):
            shutil.rmtree(file_path)
            return True
        else:
            # file not found message
            print(f'要删除的文件夹{file_path}找不到')
            return False


class video_parse: # 视频处理
    def __init__(self, pro):
        self.pro = pro #项目名称
        self.subject = "" # 主题
        self.pro_path = "" # 处理的文件路径
        self.totle_time = "" # 总时长 以文字为准
        self.mp3_time = ""  # 音乐时间
        self.word = "" # 文字内容
        self.pic_num = "" # 图片数量

    def click(time_s = None):
        if time_s != None:
            time.sleep(time_s)
        pyautogui.click()

    def doubleClick(time_s = None):
        if time_s != None:
            time.sleep(time_s)
        pyautogui.doubleClick()

    def move_click(x, y, time_s = None): # 鼠标移动到位置延时点击
        pyautogui.moveTo(x, y)
        video_parse.click(time_s)

    def jianying_init(pro_path):  # 软件打开 及找到对应工程 导入素材 pro_path是子文件夹
        time.sleep(1)
        file_path = pro_path

        pyautogui.hotkey('win', 'd') #先清空屏幕
        #优化：先检测软件是否处于打开状态，打开则保存后关闭
        os.startfile('"D:\\Program\\amaoComV4.9.exe"') #打开软件 C:\\Users\\addoi\\AppData\\Local\\JianyingPro\\Apps\\JianyingPro.exe
        time.sleep(2)

        video_parse.move_click(1100, 350, 5) #开始创作

        time.sleep(3)
        pyautogui.hotkey('ctrl', 'i') #导入素材 快捷键 ctrl I

        video_parse.move_click(1652, 67, 1)  # 查找文件路路径 先手动将文件夹弄成最大

        # pyautogui.write不支持中文输入 只能复制粘贴
        pyperclip.copy(file_path)
        pyautogui.hotkey('ctrl', 'v')
        pyautogui.press('enter')
        video_parse.move_click(1652, 600) # 移动到文件筐空白处
        pyautogui.hotkey('ctrl', 'a')
        video_parse.move_click(1971, 1295) # 点击导入

        #将音频拖入轨道 因为这里音频只有一个，所以拖入，不适用于多个情况
        video_parse.move_click(1010, 166) # 选分类
        video_parse.move_click(1010, 300) # 选音频
        video_parse.move_click(911, 159) # 选时长
        video_parse.move_click(878, 405) #选多-少
        video_parse.move_click(442, 305) # 选第二个音频
        pyautogui.dragTo(455, 1155, 1, button='left') #拖到轨道

        #将单个图片加入轨道
        video_parse.move_click(1010, 166)  # 选分类
        video_parse.move_click(1010, 357)  # 选图片
        video_parse.move_click(246, 305)  # 选第一个图片
        pyautogui.dragTo(455, 1155, 1, button='left')  # 拖到轨道


        # x, y = pyautogui.size()
        # print(x, y) # 获取屏幕分辨率
        # x, y = pyautogui.position()
        # print(x, y)

        # pyautogui.moveTo(100, 200)  # 将鼠标移动至（100，200）坐标处
        # pyautogui.moveTo(1886, 17, 1) # 该移动过程是一个持续性过程，耗时 1 秒
        # pyautogui.move(0, 50, 1) # 将鼠标向下移动 50 像素
        # pyautogui.move(-30, 0, 1)  # 将鼠标向左移动 30 像素
        # pyautogui.dragTo(1886, 200, 1, button='left') # 按住鼠标左键将目标拖拽至坐标处 耗时 1 秒
        # pyautogui.drag(300, 0, 1, button='right') # 按住鼠标右键将目标向右移动 30 个像素，该移动过程是一个持续性过程，耗时 1 秒
        # pyautogui.press('enter') # 按下 enter / F1 键
        # pyautogui.press('f1')
        # pyautogui.click() # 在当前位置单击左键
        # pyautogui.doubleClick() # 在当前位置双击左键
        # pyautogui.write('Hello world!') # 输入 “Hello World”
        # pyautogui.hotkey('command', 'a')# 组合按键 command + a
        # time.sleep(0.5)

    def set_show_time(word, mp3_time=None):  # 设置元素（图片）的显示时间
        time.sleep(1)

        video_parse.move_click(2034, 966) #将时间线设置为最小 每个图片默认5秒 所以在轴上是固定宽度
        #添加文字轨道
        video_parse.move_click(225, 83) # 点击素材框文本
        video_parse.move_click(250, 231)  # 点击默认文本
        pyautogui.dragTo(259, 1052, 1, button='left')  # 拖到轨道最开始位置
        #添加文字内容
        video_parse.move_click(2095, 251)  # 点击编辑框文本
        # video_parse.move_click(1708, 84)  # 点击文本编辑框
        pyautogui.hotkey('ctrl', 'a')
        pyperclip.copy(word)
        pyautogui.hotkey('ctrl', 'v')
        # 修改文字大小 根据字数定 修改样式  字号10-一行16个 字号20-一行8个 字号大小以一行最大字数和最大行数的最大值为准
        word_size = 160 / doc_function.get_str_row_column(word)
        word_size = int(word_size) + 1
        print("字号设置为：", word_size)
        video_parse.move_click(2156, 391)  # 点击字号设置
        pyautogui.hotkey('ctrl', 'a')
        pyperclip.copy(word_size)
        pyautogui.hotkey('ctrl', 'v') #修改字号
        video_parse.move_click(1736, 627)  # 修改样式

        # 修改文字渐入渐出
        video_parse.move_click(1796, 87)  # 点击动画
        video_parse.move_click(1802, 772) # 选择扭曲模糊进入
        video_parse.move_click(1719, 907)  # 点击动画时长设置
        pyautogui.hotkey('ctrl', 'a')
        pyperclip.copy("2.5") # 时长为2.5s
        pyautogui.hotkey('ctrl', 'v')  # 修改时长为2.5s
        video_parse.move_click(1924, 147)  # 选择出场设置
        video_parse.move_click(1673, 793) # 渐隐

        # 计算最终时长 暂时设置为1s/1字
        word_speed = 1
        totle_time = len(word) * word_speed

        # 修改文字播放时长
        mov_1s_right = 5.4 # 等比例计算右移1s所移动的像素点
        target_loc = 255 + totle_time * mov_1s_right  #目标位置 255是初始位置
        video_parse.move_click(274, 1100)  # 点击文本结束所在位置
        pyautogui.dragTo(target_loc, 1100, 1, button='left')  # 拖到轨道设置时间所在的位置
        #
        # 修改图片结束时长
        video_parse.move_click(283, 1180)  # 点击图片结束所在位置 结束位置不一样
        pyautogui.dragTo(target_loc, 1180, 1, button='left')  # 拖到轨道设置时间所在的位置

        # 修改音频结束时长
        if mp3_time > totle_time:  #mp3时间比总时间长 则裁剪
            mp3_time = int(mp3_time)
            video_parse.move_click((255 + mp3_time * mov_1s_right), 1264)  # 计算并点击音频结束所在位置
            pyautogui.dragTo(target_loc, 1280, 1, button='left')  # 拖到轨道设置时间所在的位置

        #修改音频淡入淡出
        video_parse.move_click(2091, 354)  # 点击淡入设置
        pyautogui.hotkey('ctrl', 'a')
        pyperclip.copy("2.5")  # 时长为2.5s
        pyautogui.hotkey('ctrl', 'v')  # 修改时长为2.5s

        video_parse.move_click(2091, 414)  # 点击淡出设置
        pyautogui.hotkey('ctrl', 'a')
        pyperclip.copy("2.5")  # 时长为2.5s
        pyautogui.hotkey('ctrl', 'v')  # 修改时长为2.5s


    def video_save(titel):  # 标题不能超过20个字 返回保存路径 需要将成片文件剪切到草稿文件夹 未找到文件返回空路径
        video_parse.move_click(2022, 22)  # 点击导出
        video_parse.move_click(1438, 273)  # 点击作品名称
        pyautogui.hotkey('ctrl', 'a')
        pyperclip.copy(titel)
        pyautogui.hotkey('ctrl', 'v')

        #修改路径 根据 self.subject 和 word内容 决定，还是图片所在文件位置
        video_parse.move_click(1405, 1124) # 点击导出

    def push_cloud(pro_path): # 推送到云
        print(pro_path)

    def video_publish_time(son_path, titel, p_time): #标题不能超过20个字，saved_path是子文件路径 p_time是定时发布的时间 xxxxxx 只有月日时 年分秒默认今年和0
        # print(titel)
        publish_time = time.strftime("%Y") + p_time + "00" + "00"  # 加上年 分 秒
        # 打开exe或者dy网页端

        # 从son_path查找mp4文件，使用文件类型排序，选择第一个

        # 拖拽文件上传

        # 设置标题和定时时间


    def pic_word_to_video(pro_path, word, mp3_time): # 图文成片 上传到云  剪切完成务必关闭软件 本地文件保存在pro_path中
        #文字播放速度 暂时设置为1s/1字
        #封面用第一页
        #切文字的时候图片一起切，图片不够就循环，音乐不够也循环，一切以文字为准


        # 初始化
        video_parse.jianying_init(pro_path)
        # 设置显示时间和效果
        video_parse.set_show_time(word, mp3_time)  # "《戏张先》\n\n十八新娘八十郎，\n苍苍白发对红妆。一树梨花压海棠。一树梨花压海棠。\n鸳鸯被里成双夜，一树梨花压海棠。\n一树梨花压海棠。一树梨花压海棠。"
        # 上传到云
        video_parse.push_cloud(pro_path)
        # 本地保存
        video_parse.video_save("mp4")

    def merge_mp3(subject, totle_time): # totle_time 单位s 返回合并剪切后的音乐地址
        subject_path = os.path.join(os.getcwd(), subject)
        # 根据合并后的视频总长来调整音乐时长
        song_name = doc_function.search_file("cut-")[0]
        mp3Info = eyed3.load(song_name)  # 检测音乐时长
        mp3_time = mp3Info.info.time_secs

        circle_num = totle_time / mp3_time # 计算叠加mp3的次数
        sound_signal = AudioSegment.from_mp3(song_name)
        num = 0
        sound_output = ""
        while num < (circle_num+1):
            sound_output = sound_output + sound_signal
            num = num + 1

        # 粗略叠加后对其进行精准时间裁剪和重命名
        sound_output = sound_output[:totle_time * 1000]  # 提取片段 ms为单位
        awesome = sound_output.fade_in(5000).fade_out(3000)  # 渐进渐出

        filepath, tempfilename = os.path.split(song_name)  # 剪切的音乐重命名
        tempfilename = tempfilename.replace('cut-', 'merge-')
        song_cut = filepath + "\\" + tempfilename
        awesome.export(song_cut)  # 导出音乐

        return song_cut


    def merge_publish(subject, target): # 成功然后None 失败返回对应的子文件夹
        # 执行jianying_init的前半部分
        totle_time = 0
        for son in target:
            if son[0] == "0":
                son = son[1]  # 去除前面的无效0
            subject_path = os.path.join(os.getcwd(), subject)
            son_path = os.path.join(subject_path, son)
            if os.path.exists(son_path):
                print(son_path)
                # 将文件加入到素材 同时累加视频时长
                mp4_name = doc_function.search_file("mp4", son_path)[0]  # 获取子文件夹中的视频路径
                clip = VideoFileClip(mp4_name)
                totle_time = totle_time + clip.duration
                print_d(clip.duration)  # seconds

            else: # 不存在 则返回合并失败
                print(f'要合并的子文件夹{son_path}找不到')
                return son

        # 根据最终时长修改音乐时间
        video_parse.merge_mp3(subject, totle_time)

        # 将音乐加入素材

        # 将所有素材拖到轨道

        # 导出、保存、发布

        return None



class email_parse:  #邮件处理
    def __init__(self,remote_server_url,email_url,password):
        self.remote_server_url = remote_server_url
        self.email_url = email_url
        self.password = password

        self.subject_name = " "

    def decode_str(s):  # 解码字符串
        value, charset = decode_header(s)[0]
        if charset:
            value = value.decode(charset)
        return value

    def is_chinese(string): # 检查整个字符串是否包含中文
        for ch in string:
            if u'\u4e00' <= ch <= u'\u9fff':
                return True

        return False

    def set_charset(msg):  # 设置字符集
        charset = msg.get_charset()  # 获取字符集
        if charset is None:
            content_type = msg.get('Content-Type', '').lower()
            pos = content_type.find('charset=')
            if pos >= 0:
                charset = content_type[pos + 8:].strip()
        return charset

    def send_email(msg_from, passwd, msg_to, subject_rx, text_content, file_path=None): # 邮箱数据返回
      msg = MIMEMultipart()
      subject = subject_rx  # 主题
      text = MIMEText(text_content)
      msg.attach(text)

      if file_path:  # 最开始的函数参数我默认设置了None ，想添加附件，自行更改一下就好
          docFile = file_path
          docApart = MIMEApplication(open(docFile, 'rb').read())
          docApart.add_header('Content-Disposition', 'attachment', filename=docFile)
          msg.attach(docApart)
          print('发送附件:', file_path)
      msg['Subject'] = subject
      msg['From'] = msg_from
      msg['To'] = msg_to
      try:
          s = smtplib.SMTP_SSL("smtp.qq.com", 465)
          s.login(msg_from, passwd)
          s.sendmail(msg_from, msg_to, msg.as_string())
          print("邮件发送成功")
      except smtplib.SMTPException as e:
          print("邮件发送失败")
      finally:
          s.quit()

    def get_music_pic_url(key_word): #获取歌曲对应的图片链接 key_word是关键字 指定搜索引擎https://image.baidu.com/  返回地址
        print('进行数据爬取')
        from selenium import webdriver
        from selenium.webdriver.chrome.service import Service
        from selenium.webdriver.common.by import By

        url = 'https://image.baidu.com/'

        s = Service(r'C:\Users\addoi\AppData\Local\Google\Chrome\Application\chromedriver.exe')

        options = webdriver.ChromeOptions()
        # 设置为开发者模式，防止被各大网站识别出来使用了Selenium 没什么用
        options.add_argument("--disable-blink-features=AutomationControlled")
        options.add_experimental_option('excludeSwitches', ['enable-automation'])
        driver = webdriver.Chrome(service=s, options=options)

        driver.get(url)

        # 在搜索框自动输入内容
        driver.find_elements(By.XPATH, '//*[@id="kw"]')[0].send_keys(key_word)
        driver.find_elements(By.XPATH, '//*[@id="homeSearchForm"]/span[2]/input')[0].click()

        print(f'爬取关键字 {key_word} 的url地址是 {driver.current_url}')
        return driver.current_url


    def email_back(file_type): # 进行邮箱数据的返回 不同文件类型返回不同信息
        print('邮箱数据返回...')
        file_path = None
        if qq_email_tx.main_body == "":
            qq_email_tx.main_body = "没有匹配项，请检查主文格式和附件后重新发送，以下为示例\r\n 1、主题+mp3文件+时间戳（xxx-xxx）" \
                                    "\r\n2、图片\r\n3、图片序号（xx + 文字 + 换行\r\n4、ok/no + 子文件序号(xx) + 发布时间(月日时 xxxxxx) + 标题（2-20字）" \
                                    "\r\n5、合并文件（xx）-合并文件（xx）"

        if qq_email_rx.filename != "":  # 有附件
            # 1、收到mp3和时间戳 返回剪辑后的mp3和“请发图片”
            if qq_email_rx.filename[0].find(".mp3") != -1:  # 音频文件   or qq_email_rx.filename[0].find(".flac") != -1
                if qq_email_rx.main_body[:7].find(" ") != -1 and qq_email_rx.main_body[:3].isdigit() == True and qq_email_rx.main_body[4:7].isdigit() == True:  # 判断条件是有空格且全是数字 格式104 155 1分4秒到1分55秒
                    song_name = doc_function.search_file("mp3-")[0]
                    start_time = int(qq_email_rx.main_body[0]) * 60 + int(qq_email_rx.main_body[1:3])
                    end_time = int(qq_email_rx.main_body[4]) * 60 + int(qq_email_rx.main_body[5:7])

                    if song_name == None:
                        qq_email_tx.main_body = "1、未找到MP3文件" + "\r\n请发MP3文件！！！\r\n"
                    else:
                        mp3Info = eyed3.load(song_name)  # 检测音乐时长
                        mp3_time = mp3Info.info.time_secs
                        if start_time >= end_time or end_time > mp3_time:
                            qq_email_tx.main_body = f'1、时间不对, 应在{mp3_time}秒以内且前后不冲突 格式ex 123 145 '
                        else:  # 剪切 渐进渐出 重命名 保存（+cut） 返回
                            song = AudioSegment.from_mp3(song_name)  # 导入音乐
                            song = song[start_time * 1000:end_time * 1000]  # 提取片段 ms为单位
                            awesome = song.fade_in(5000).fade_out(3000)  # 渐进渐出

                            filepath, tempfilename = os.path.split(song_name)  # 剪切的音乐重命名
                            tempfilename = tempfilename.replace('mp3-', 'cut-')
                            song_cut = filepath + "\\" + tempfilename
                            awesome.export(song_cut)  # 导出音乐
                            file_path = song_cut
                            qq_email_tx.main_body = "1、收到mp3和时间戳，请查收剪辑后的mp3" + "-------请返回图片！！！"
                else:
                    qq_email_tx.main_body = "1、收到mp3,未收到时间戳" + "-------请发时间戳！！！"

            # 2、收到图片 保存路径为01234  返回”请发文字内容！！！“
            elif qq_email_rx.filename[0].find(".jpg") != -1 or qq_email_rx.filename[0].find(".bmp") != -1 or qq_email_rx.filename[0].find(".png") != -1:  # 图片文件
                qq_email_tx.main_body = "2、收到图片，序号为" + qq_email_tx.main_body + "-------请发文字（格式为：对应图片序号+文字+换行）！！！"

        else:  # 没有附件
            # 3、收到文字  上传成品到云 进行确认
            if qq_email_rx.main_body.find("\n") != -1 and qq_email_rx.main_body.find(" ") != -1 and \
                    email_parse.is_chinese(qq_email_rx.main_body[:5]) == True and qq_email_rx.main_body[0].isdigit() == True: # 判断条件是前5个字符有汉字、第一个字符是数字且有换行和空格

                # 查找是否含有此序号对应的照片
                digit_len = qq_email_rx.main_body.find(" ")
                check_file = "pic" + qq_email_rx.main_body[:digit_len] + "-"
                print_d(check_file)
                file_list = doc_function.search_file(check_file)
                if file_list[0] == None: # 未找到对应的照片
                    qq_email_tx.main_body = f'3、收到文字，未找到和文字序号对应的图片-------请重发文字（格式为：对应图片序号+空格+文字+换行）！！！'
                else:
                    # 将对应序号图片放到以文字序号为子文件夹的路径下
                    son_file_path = os.getcwd() + "\\" + qq_email_rx.Subject + "\\" + qq_email_rx.main_body[:digit_len]
                    print_d(son_file_path)
                    doc_function.mkdir(son_file_path)  # 创建文件夹
                    doc_function.copyfile(file_list[0], son_file_path + "\\") # 将图片复制到对应子文件夹
                    # 图文成片
                    song_name = doc_function.search_file("cut-")[0]
                    mp3Info = eyed3.load(song_name) # 检测音乐时长
                    mp3_time = mp3Info.info.time_secs
                    word_count = qq_email_rx.main_body.find("---原始邮件---") - 8 # 默认有正文则前有8个字节
                    word = qq_email_rx.main_body[(digit_len + 1):word_count]

                    # video_parse.pic_word_to_video(son_file_path, word, mp3_time)

                    qq_email_tx.main_body = f'3、收到文字，请在剪映云上进行成片确认或发布-------请回复"ok/no" + "子文件序号(xx)" + "发布时间(月日时 xxxxxx)" + "标题（2-20字）" ex： ok 02 010415 测试 \r\n------也可发送子文件夹序号1-2-3进行混剪发送！！！'

            # 4、先”ok“发布  ”no“删除  再子文件序号，然后时间是定时发布 后面是标题（发布的标题不能超过20个字） ex： ok 2 010415 测试 - 1月4日15点将子文件夹标题改为测试进行发布
            elif ((qq_email_rx.main_body[:5].find("ok") != -1 or qq_email_rx.main_body[:5].find("no") != -1)) and qq_email_rx.main_body[3].isdigit() == True:
                word_count = qq_email_rx.main_body.find("---原始邮件---") - 8
                if (word_count < 3 and qq_email_rx.main_body[:5].find("ok") != -1) or word_count > 32:  # 标题长度判断
                    qq_email_tx.main_body = f'4、收到回复，标题长度不对-------请回复"ok/no" + "子文件序号(xx)" + "发布时间(月日时 xxxxxx)" + "标题（2-20字）" ex： ok 02 010415 测试 ！！！'

                # 各项内容 ex： ok 02 010415 测试
                son_file = qq_email_rx.main_body[3:5]
                if qq_email_rx.main_body[3] == "0":
                    son_file = qq_email_rx.main_body[4] # 去除前面的无效0

                son_file_path = os.getcwd() + "\\" + qq_email_rx.Subject + "\\" + son_file
                if qq_email_rx.main_body[:5].find("ok") != -1: # 进行标题修改及定时发布
                    mp4_titel = qq_email_rx.main_body[13:(word_count-1)]
                    publish_time = qq_email_rx.main_body[6:12] # 加上年 分 秒
                    if os.path.exists(son_file_path):
                        video_parse.video_publish_time(son_file_path, mp4_titel, publish_time) # 修改标题 定时发布
                        qq_email_tx.main_body = f'4、收到回复，视频 {mp4_titel} 将于 {publish_time[0:2]}月{publish_time[2:4]}日{publish_time[4:6]}时 进行发布'
                    else:
                        qq_email_tx.main_body = f'4、要定时发布的文件夹 {son_file_path} 找不到'

                elif qq_email_rx.main_body[:5].find("no") != -1: # 删除son_file
                    if doc_function.delete_files(son_file_path) == True:
                        qq_email_tx.main_body = f'4、收到回复，文件夹已删除'
                    else:
                        qq_email_tx.main_body = f'4、要删除的文件夹 {son_file_path} 找不到'

            # 5、多个文件的合并发布 立即发布
            elif qq_email_rx.main_body[0:2].isdigit() == True and qq_email_rx.main_body[2] == '-' and qq_email_rx.main_body[3:5].isdigit() == True: # 格式是1-2-3
                son_num_len = qq_email_rx.main_body.find(" ")
                son = []
                loc = 0
                # 进行合并文件的查找
                word_count = qq_email_rx.main_body.find("---原始邮件---") - 8  # 默认有正文则前有8个字节
                while qq_email_rx.main_body.find("-", loc) != -1 and loc < (word_count-1):
                    loc = qq_email_rx.main_body.find("-", loc)
                    son.append(qq_email_rx.main_body[(loc-2):loc])
                    loc = loc + 2

                son.append(qq_email_rx.main_body[(word_count - 2):word_count])
                #进行合并发布 传入主题和son
                result = video_parse.merge_publish(qq_email_rx.Subject, son)
                if result == None:
                    qq_email_tx.main_body = f'5、收到回复，已将 {son} 合并发布！！！'
                else:
                    qq_email_tx.main_body = f'5、收到回复，子文件夹 {result} 找不到！！！'

        qq_email_tx.printf("发送")
        if DEBUG == 0:  # 调试的时候不返回数据
            email_parse.send_email(email_url, password, email_msg_to, qq_email_rx.Subject, qq_email_tx.main_body, file_path)


    def download_file(msg):  # 保存附件到指定路径
        fpath = os.getcwd()
        path_name = qq_email_rx.Subject  # 获取主题名字，作为文件夹名字

        out_file = fpath + "\\" + path_name
        print('文件保存路径是：', out_file)
        doc_function.mkdir(out_file)  #创建文件夹

        # 获取邮件主体信息
        attachment_files = []
        for part in msg.walk():
            file_name = part.get_filename()  # 获取附件名称类型
            contentType = part.get_content_type()  # 获取数据类型
            mycode = part.get_content_charset()  # 获取编码格式
            if file_name:
                h = Header(file_name)
                dh = decode_header(h)  # 对附件名称进行解码
                filename_download = dh[0][0]
                if dh[0][1]:
                    filename_download = email_parse.decode_str(str(filename_download, dh[0][1]))  # 将附件名称可读化
                attachment_files.append(filename_download)
                data = part.get_payload(decode=True)  # 下载附件
                with open(out_file + "\\" + filename_download, 'wb') as f:  # 在当前目录下创建文件，注意二进制文件需要用wb模式打开
                    f.write(data)  # 保存附件
                # 进行文件重命名，加上时间
                qq_email_rx.filename = attachment_files
                src = out_file + "\\" + filename_download
                if qq_email_rx.filename[0].find(".mp3") != -1:  # 音频文件
                    dst = out_file + "\\" + "mp3-" + qq_email_rx.Date + filename_download
                    time.sleep(2) # 为下载和重命名留时间
                elif qq_email_rx.filename[0].find(".jpg") != -1 or qq_email_rx.filename[0].find(".bmp") != -1 or qq_email_rx.filename[0].find(".png") != -1:  # 图片文件 重命名-在原类型数量基础上递增
                    pic_name = doc_function.search_file("pic")
                    if pic_name == None:
                        pic_num = 0
                    else:
                        pic_num = len(pic_name)
                    dst = out_file + "\\" + "pic" + str(pic_num) + "-" + qq_email_rx.Date + filename_download
                    qq_email_tx.main_body = qq_email_tx.main_body + str(pic_num) + "-"
                else: # 其它类型
                    dst = out_file + "\\" + qq_email_rx.Date + filename_download

                try:
                    os.rename(src, dst)
                except: # 文件重复异常处理
                    os.remove(dst)
                    os.rename(src, dst)

                print(f'附件 {filename_download} 已下载及重命名完成')

            elif contentType == 'text/plain':  # or contentType == 'text/html':
                # 输出正文 也可以写入文件
                data = part.get_payload(decode=True)
                content = data.decode(mycode)
                qq_email_rx.main_body = content
                # print('正文：', content)
        # print('附件文件名列表', qq_email_rx.filename)

    def get_email_title(msg):   # 获取发件人，主题和发送日期  返回主题名字
        for header in ['From', 'Subject', 'Date']:  # 遍历获取发件人，主题的相关信息
            value = msg.get(header, '')  # 获取邮件头的内容
            if value != '':
                if header == 'From':  # 解析字符串中的邮件地址
                    hdr, addr = parseaddr(value)
                    name = email_parse.decode_str(hdr)  # 解码字符串
                    value = '%s <%s>' % (name, addr)
                    qq_email_rx.From = name

                elif header == 'Subject': # 获取主题的信息，并解码
                    value = email_parse.decode_str(value)  # 解码字符串
                    if value.find("回复") != -1:  # 是回复信息
                        # 以回复后面的内容以此为文件夹
                        qq_email_rx.Subject = value[3:]
                        print(qq_email_rx.Subject)
                    else:
                        qq_email_rx.Subject = value

                elif header == 'Date':  # 获取日期的信息，并解码
                    value = email_parse.decode_str(value)  # 解码字符串
                    print(value)
                    time_format = datetime.datetime.strptime(value, '%a, %d %b %Y %H:%M:%S +%f')
                    qq_email_rx.Date = time_format.strftime("%Y-%m-%d %H-%M-%S-")
                    print(qq_email_rx.Date)


                print('%s: %s' % (header, value))

    def get_email_update(space): # 每隔space秒检测一次是否更新，进行状态返回，如果更新返回最新的邮件数量，否则返回0
        if DEBUG == 0:
            time.sleep(space)

        server = imaplib.IMAP4_SSL(remote_server_url, 993)
        server.login(email_url, password)
        server.select('INBOX')
        status, data = server.search(None, "ALL")
        if status != 'OK':
            raise Exception('read email error')
        emailids = data[0].split()
        mail_counts = len(emailids)
        current_time = datetime.datetime.now()
        current_time = current_time.strftime("%Y-%m-%d-%H:%M:%S")
        print(f'{str(current_time)}-邮件数量是 {mail_counts}')
        if mail_counts > qq_email_rx.count and qq_email_rx.count != 0 or DEBUG == 1:
            qq_email_rx.count = mail_counts
            return qq_email_rx.count
        else:
            qq_email_rx.count = mail_counts
            return 0

    def main_parse_Email(self):  # 处理email数据
        qq_email_rx.reset()
        qq_email_tx.reset()
        counts = email_parse.get_email_update(check_time)

        if counts == 0: #未更新
            return
        else:
            server = imaplib.IMAP4_SSL(self.remote_server_url, 993)
            server.login(self.email_url, self.password)
            server.select('INBOX')
            status, data = server.search(None, "ALL")
            if status != 'OK':
                raise Exception('read email error')
            emailids = data[0].split()
            mail_counts = counts

            status, edata = server.fetch(emailids[mail_counts-1], '(RFC822)')
            msg = email.message_from_bytes(edata[0][1])

            email_parse.get_email_title(msg) # 获取email title
            if qq_email_rx.From.find("叶绿素") == -1 and DEBUG == 0: # 不是指定邮箱的邮件
                print("不是指定邮箱发的文件")
                return
            elif qq_email_rx.Subject.find(" ") < 2  and DEBUG == 0: # 不是歌手+歌名的格式
                print("不是歌手+歌名的格式")
                return

            # 附件保存
            email_parse.download_file(msg)

            qq_email_rx.printf("接收")

            # 进行数据返回
            email_parse.email_back(qq_email_rx.filename)




if __name__ == "__main__":
    print("start music cut from email !!!!")
    # video_parse.jianying_init()
    # video_parse.set_show_time("《戏张先》\n\n十八新娘八十郎，\n苍苍白发对红妆。一树梨花压海棠。一树梨花压海棠。\n鸳鸯被里成双夜，一树梨花压海棠。\n一树梨花压海棠。一树梨花压海棠。")
    # video_parse.video_save("测试脚本")
    qq_email_rx = email_data()
    qq_email_tx = email_data()
    email_rx = email_parse(remote_server_url, email_url, password)
    # video = video_parse("pic_word_to_video")
    while 1:
        try:
            email_rx.main_parse_Email()
        except:
            print("error")
            traceback.print_exc()
            continue





